using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using FU.Capstones.IMS.Web.Common;
using FU.Capstones.IMS.Web.Common.InventoryServiceProxy.DataContracts;
using FU.Capstones.IMS.Web.Common.InventoryServiceProxy.EventArgs;
using FU.Capstones.IMS.Web.Silverlight.Controls;
using FU.Capstones.IMS.Web.Silverlight.Models;
using FU.Capstones.IMS.Web.Silverlight.Popups;
using Microsoft.Practices.Prism.Commands;
using Navigation.Silverlight;

namespace FU.Capstones.IMS.Web.Silverlight.ViewModels
{
    public class ProductDetailViewModel : ViewModelBase
    {
        public ProductDetailViewModel()
        {
            Model = new ProductDetailModel();
            ((ProductDetailModel)Model).GetSingleProductCompleted += DoGetSingleProductCompleted;
            ((ProductDetailModel)Model).InsertProductCompleted += DoInsertProductCompleted;
            ((ProductDetailModel)Model).UpdateProductCompleted += DoUpdateProductCompleted;
            ((ProductDetailModel)Model).GetMaterialCollectionCompleted += GetMaterialCollectionCompleted;
            ((ProductDetailModel)Model).InsertBuiltupMaterialCompleted += DoInsertBuiltupMaterialCompleted;
            ((ProductDetailModel)Model).DeleteProductBuiltupCompleted += DoDeleteProductBuiltupCompleted;

            IsFirstLoaded = false;
            ErrorMessageVisibility = Visibility.Collapsed;
            MessageVisibility = Visibility.Collapsed;

            ServiceCallCounter += ((ProductDetailModel)Model).GetMaterialCollectionAsync();

            CanEditOrAdd = CurrentUser.CanEditProduct || CurrentUser.CanAddProduct;
            CanAdd = CurrentUser.CanAddProduct;
        }

        #region Do Completed Methods

        void GetMaterialCollectionCompleted(object sender, CollectionFeedbackCompletedEventArgs<Material> e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                SetMessageVisibility(false);
            }
            else
            {
                Message = e.Result.Message;
                SetMessageVisibility(e.Result.IsSuccessful);
                if (e.Result.IsSuccessful)
                {
                    MaterialCollection = new PagedCollectionView(e.Result.Data);
                    MapCollection();
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        void DoUpdateProductCompleted(object sender, FeedbackCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                SetMessageVisibility(false);
            }
            else
            {
                Message = e.Result.Message;
                SetMessageVisibility(e.Result.IsSuccessful);

                if (e.Result.IsSuccessful)
                {
                    MaterialCollection = new PagedCollectionView(MaterialCollection.SourceCollection.Cast<Material>().OrderByDescending(m => m.IsSelected));
                    Backup();
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        void DoInsertProductCompleted(object sender, SingleFeedbackCompletedEventArgs<int> e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                SetMessageVisibility(false);
            }
            else
            {
                Message = e.Result.Message;
                SetMessageVisibility(e.Result.IsSuccessful);
                if (e.Result.IsSuccessful)
                {
                    isCreateNew = false;
                    Product.ProductID = e.Result.Data;
                    MaterialCollection = new PagedCollectionView(MaterialCollection.SourceCollection.Cast<Material>().OrderByDescending(m => m.IsSelected));
                    Backup();
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        void DoInsertBuiltupMaterialCompleted(object sender, FeedbackCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                SetMessageVisibility(false);
            }
            else
            {
                Message = e.Result.Message;
                SetMessageVisibility(e.Result.IsSuccessful);
                if (e.Result.IsSuccessful)
                {
                    isCreateNew = false;
                    
                    Backup();
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        void DoGetSingleProductCompleted(object sender, SingleFeedbackCompletedEventArgs<Product> e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                SetMessageVisibility(false);
            }
            else
            {
                Message = e.Result.Message;
                SetMessageVisibility(e.Result.IsSuccessful);
                if (e.Result.IsSuccessful)
                {
                    Product = new Product()
                    {
                        ProductCode = e.Result.Data.ProductCode,
                        Description = e.Result.Data.Description,
                        ProductID = e.Result.Data.ProductID,
                        ProductName = e.Result.Data.ProductName,
                        MaterialCollection = e.Result.Data.MaterialCollection
                    };
                    Backup();
                    MapCollection();
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        void DoDeleteProductBuiltupCompleted(object sender, FeedbackCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Message = e.Error.Message;
                MessageVisibility = Visibility.Visible;
            }
            else
            {
                Message = e.Result.Message;
                if (e.Result.IsSuccessful)
                {
                    ServiceCallCounter += ((ProductDetailModel)Model).GetSingleProductAsync(Product.ProductID);
                }
            }
            ServiceCallCounter -= WebConstants.MagicNumer;
        }

        #endregion

        #region Commands

        #region SaveCommand

        private DelegateCommand<object> saveCommand;
        public DelegateCommand<object> SaveCommand
        {
            get
            {
                if (saveCommand == null)
                    saveCommand = new DelegateCommand<object>(DoSaveCommand);
                return saveCommand;
            }
        }

        private void DoSaveCommand(object obj)
        {
            Product.ValidateAll();
            if (!Product.HasErrors)
            {
                if (isCreateNew)
                {
                    ServiceCallCounter += ((ProductDetailModel)Model).InsertProductAsync(Product);
                    

                }
                else
                {
                    ServiceCallCounter += ((ProductDetailModel)Model).UpdateProductAsync(Product);
                }
            }
            else
            {
                Message = WebConstants.InvalidInputDataMessage;
                SetMessageVisibility(false);
            }
        }

        #endregion

        #region CancelCommand

        private DelegateCommand<object> cancelCommand;
        public DelegateCommand<object> CancelCommand
        {
            get
            {
                if (cancelCommand == null)
                    cancelCommand = new DelegateCommand<object>(DoCancelCommand);
                return cancelCommand;
            }
        }

        private void DoCancelCommand(object obj)
        {
            NavigationManager.NavigateTo(WebConstants.NavigationPages.ProductList);
        }

        #endregion

        #region ResetCommand

        private DelegateCommand<object> resetCommand;
        public DelegateCommand<object> ResetCommand
        {
            get
            {
                if (resetCommand == null)
                    resetCommand = new DelegateCommand<object>(DoResetCommand);
                return resetCommand;
            }
        }

        private void DoResetCommand(object obj)
        {
            if (isCreateNew)
                Product = new Product();
            else
            {
                Product = productTemp;
                Backup();
            }
        }

        #endregion

        #region SelectCommand

        private DelegateCommand<int?> selectCommand;
        public DelegateCommand<int?> SelectCommand
        {
            get
            {
                if (selectCommand == null)
                {
                    selectCommand = new DelegateCommand<int?>(DoSelectCommand);
                }
                return selectCommand;
            }
        }

        private void DoSelectCommand(int? obj)
        {
            if (obj.HasValue && obj.Value > 0)
            {
                Material material =
                    MaterialCollection.SourceCollection.Cast<Material>().FirstOrDefault(m => m.MaterialID == obj.Value);
                if (product.MaterialCollection == null)
                {
                    product.MaterialCollection = new ObservableCollection<Material>();
                }
                if (material.IsSelected)
                {
                    product.MaterialCollection.Add(material);
                }
                else
                {
                    product.MaterialCollection.Remove(material);
                }

            }
        }

        #endregion

        #region DeleteCommand

        private DelegateCommand<int?> deleteCommand;
        public DelegateCommand<int?> DeleteCommand
        {
            get
            {
                if (deleteCommand == null)
                    deleteCommand = new DelegateCommand<int?>(DoDeleteCommand);
                return deleteCommand;
            }
        }

        private void DoDeleteCommand(int? obj)
        {
            if (obj.HasValue && obj.Value != 0) 
            {
                DeleteConfirmationPopup popup = new DeleteConfirmationPopup();
                popup.Show();
                popup.Closed += (sender, e) =>
                {
                    if (popup.DialogResult.HasValue && popup.DialogResult.Value)
                    {
                        ServiceCallCounter +=
                            ((ProductDetailModel)Model).DeleteBuiltupAsync(Product.ProductID, obj.Value);
                        
                        Message = "Deleting the selected material!";
                    }
                };
            }
            
        }

        #endregion

        #endregion

        #region Binding Properties

        private Product product;
        public Product Product
        {
            get { return product; }
            set
            {
                if (!ReferenceEquals(product, value))
                {
                    product = value;
                    RaisePropertyChanged(() => Product);
                }
            }
        }

        private PagedCollectionView materialCollection;
        public PagedCollectionView MaterialCollection
        {
            get { return materialCollection; }
            set
            {
                if (!ReferenceEquals(materialCollection, value))
                {
                    materialCollection = value;
                    RaisePropertyChanged(() => MaterialCollection);
                }
            }
        }

        private bool isCreateNew;
        public bool IsCreateNew
        {
            get { return isCreateNew; }
            set
            {
                if (!ReferenceEquals(isCreateNew, value))
                {
                    isCreateNew = value;
                    RaisePropertyChanged(() => IsCreateNew);
                }
            }
        }

        #endregion

        #region Fields

        
        private bool isMapped;
        private Product productTemp;

        #endregion

        #region Implementation of INavigationAware

        public override void OnNavigate(object extraData)
        {
            int? partnerID = (int?)extraData;
            isCreateNew = (partnerID.HasValue == false || partnerID.Value == 0);
            if (!isCreateNew)
            {
                ServiceCallCounter += ((ProductDetailModel)Model).GetSingleProductAsync(partnerID.Value);
            }
            else
            {
                Product = new Product();
            }
            Message = "Đang kết nối tới máy chủ...";
        }

        public override void OnLeave()
        {
            //throw new NotImplementedException();
        }

        #endregion

        private void Backup()
        {
            if (Product != null)
            {
                productTemp = new Product()
                {
                    ProductCode = product.ProductCode,
                    Description = product.Description,
                    ProductID = product.ProductID,
                    ProductName = product.ProductName
                };
                if (product.MaterialCollection != null)
                {
                    productTemp.MaterialCollection = new ObservableCollection<Material>();
                    foreach (var material in product.MaterialCollection)
                    {
                        productTemp.MaterialCollection.Add(new Material() { MaterialID = material.MaterialID });
                    }
                }
            }
        }

        private void MapCollection()
        {
            if (!isMapped)
            {
                if (product != null)
                {
                    if (product.MaterialCollection != null && MaterialCollection != null)
                    {
                        foreach (Material material in MaterialCollection)
                        {
                            material.Quantity = 0;
                        }

                        for (int count = 0; count < product.MaterialCollection.Count; count ++ )
                        {
                            Material material = product.MaterialCollection[count];

                            Material xmaterial = MaterialCollection.SourceCollection.Cast<Material>().FirstOrDefault(m =>
                                                                                           {
                                                                                               if (m.MaterialID == material.MaterialID)
                                                                                               {
                                                                                                   m.IsSelected = true;
                                                                                                   m.Quantity = material.Quantity;
                                                                                                   return true;
                                                                                               }

                                                                                               return false;
                                                                                           });
                            if (xmaterial != null && xmaterial.MaterialID > 0)
                            {
                                product.MaterialCollection[count] = xmaterial;
                            }
                            else
                            {
                                product.MaterialCollection.RemoveAt(count);
                                count--;
                            }
                        }
                        isMapped = true;

                        MaterialCollection = new PagedCollectionView(MaterialCollection.SourceCollection.Cast<Material>().OrderByDescending(m=>m.IsSelected));
                    }

                }
            }
        }
    }
}
